HTML5 多媒体与绘图面试题全解析
一、核心要点速览
💡 核心考点
- audio/video: 原生音视频播放及控制
- Canvas: 2D 绘图 API 及应用场景
- SVG: 矢量图形与 Canvas 对比
- 媒体事件: 加载、播放、暂停等事件处理
二、音视频标签详解
1. audio 标签使用
html
<!-- 基础用法 -->
<audio controls autoplay loop preload="metadata">
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
您的浏览器不支持 audio 标签
</audio>
<!-- 重要属性 -->
<audio
controls <!-- 显示控制条 -->
autoplay <!-- 自动播放(可能被浏览器阻止)-->
loop <!-- 循环播放 -->
muted <!-- 静音 -->
preload="auto" <!-- 预加载:none|metadata|auto -->
>
<source src="audio.mp3" type="audio/mpeg">
<track
kind="captions"
src="captions.vtt"
srclang="zh"
label="中文字幕"
>
</audio>2. video 标签使用
html
<video
width="640"
height="480"
controls
poster="cover.jpg"
preload="metadata"
muted
playsinline <!-- iOS 禁止自动全屏 -->
webkit-playsinline
>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<!-- 多分辨率适配 -->
<source src="video-720p.mp4" type="video/mp4" media="(min-width: 1200px)">
<source src="video-480p.mp4" type="video/mp4" media="(min-width: 768px)">
<source src="video-360p.mp4" type="video/mp4">
<!-- 字幕 -->
<track
kind="subtitles"
src="subs.vtt"
srclang="zh"
label="中文"
default
>
您的浏览器不支持 video 标签
</video>3. JavaScript 控制媒体
javascript
const video = document.querySelector('video')
// 播放控制
video.play() // 播放
video.pause() // 暂停
video.currentTime = 100 // 跳转到 100 秒
// 属性设置
video.volume = 0.5 // 音量 50%
video.playbackRate = 1.5 // 1.5 倍速
video.muted = true // 静音
video.loop = true // 循环
// 获取信息
console.log(video.duration) // 总时长(秒)
console.log(video.currentTime) // 当前时间
console.log(video.paused) // 是否暂停
console.log(video.ended) // 是否结束
// 监听事件
video.addEventListener('play', () => {
console.log('开始播放')
})
video.addEventListener('pause', () => {
console.log('暂停播放')
})
video.addEventListener('timeupdate', () => {
const percent = (video.currentTime / video.duration) * 100
console.log(`播放进度:${percent.toFixed(2)}%`)
})
video.addEventListener('ended', () => {
console.log('播放完成')
})
video.addEventListener('waiting', () => {
console.log('缓冲中...')
})
video.addEventListener('canplay', () => {
console.log('可以播放了')
})4. 媒体事件时序图
时间 → ─────────────────────────────────────────────────►
视频加载播放流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────┐
│ 加载视频 │
└────┬────┘
│
▼
┌─────────────┐
│ loadstart │ ← 开始加载
└──────┬──────┘
│
▼
┌─────────────┐
│ durationchange│ ← 获取到时长
└──────┬──────┘
│
▼
┌─────────────┐
│ loadeddata │ ← 当前帧可用
└──────┬──────┘
│
▼
┌─────────────┐
│ loadedmetadata│ ← 元数据加载完成
└──────┬──────┘
│
▼
┌─────────────┐
│ canplay │ ← 可以开始播放
└──────┬──────┘
│
▼
┌─────────────┐
│ play() │ ← 开始播放
└──────┬──────┘
│
▼
┌─────────────┐
│ timeupdate │ ← 持续触发 (每 250ms)
└──────┬──────┘
│
▼
┌─────────────┐
│ ended │ ← 播放结束
└─────────────┘
常用事件说明:
✓ loadstart: 加载开始
✓ progress: 加载进度
✓ durationchange: 时长变化
✓ loadeddata: 当前帧数据就绪
✓ loadedmetadata: 元数据就绪
✓ canplay: 可以播放
✓ playing: 正在播放
✓ pause: 暂停
✓ timeupdate: 时间更新
✓ ended: 播放结束
✓ error: 加载错误
✓ waiting: 缓冲等待
✓ seeking: 跳转中
✓ seeked: 跳转完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━三、Canvas 绘图详解
1. Canvas 基础
html
<canvas id="myCanvas" width="800" height="600"></canvas>javascript
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')
// 1. 绘制矩形
ctx.fillStyle = '#FF0000'
ctx.fillRect(10, 10, 100, 100) // 填充矩形
ctx.strokeStyle = '#000000'
ctx.lineWidth = 2
ctx.strokeRect(120, 10, 100, 100) // 描边矩形
ctx.clearRect(230, 10, 100, 100) // 清除矩形
// 2. 绘制路径
ctx.beginPath() // 开始路径
ctx.moveTo(50, 200) // 移动到起点
ctx.lineTo(150, 200) // 画线
ctx.lineTo(100, 300) // 画线
ctx.closePath() // 闭合路径
ctx.fillStyle = 'blue'
ctx.fill() // 填充
ctx.strokeStyle = 'black'
ctx.stroke() // 描边
// 3. 绘制圆形
ctx.beginPath()
ctx.arc(300, 200, 50, 0, Math.PI * 2) // 圆心、半径、起始角、结束角
ctx.fillStyle = 'green'
ctx.fill()
// 4. 绘制文字
ctx.font = '30px Arial'
ctx.fillStyle = 'black'
ctx.fillText('Hello Canvas', 50, 400) // 填充文字
ctx.strokeText('Hello Canvas', 50, 450) // 描边文字
// 5. 绘制渐变
const gradient = ctx.createLinearGradient(100, 500, 300, 500)
gradient.addColorStop(0, 'red')
gradient.addColorStop(1, 'blue')
ctx.fillStyle = gradient
ctx.fillRect(100, 500, 200, 50)2. 完整绘图示例
javascript
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 绘制一个笑脸
function drawSmiley(x, y, radius) {
// 1. 脸部
ctx.beginPath()
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.fillStyle = '#FFD700'
ctx.fill()
ctx.strokeStyle = '#000'
ctx.lineWidth = 2
ctx.stroke()
// 2. 左眼
ctx.beginPath()
ctx.arc(x - radius/3, y - radius/5, radius/10, 0, Math.PI * 2)
ctx.fillStyle = '#000'
ctx.fill()
// 3. 右眼
ctx.beginPath()
ctx.arc(x + radius/3, y - radius/5, radius/10, 0, Math.PI * 2)
ctx.fillStyle = '#000'
ctx.fill()
// 4. 嘴巴
ctx.beginPath()
ctx.arc(x, y, radius/2, 0.2 * Math.PI, 0.8 * Math.PI)
ctx.strokeStyle = '#000'
ctx.lineWidth = 3
ctx.stroke()
}
drawSmiley(200, 200, 100)3. Canvas 动画示例
javascript
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
let ball = {
x: 50,
y: 50,
vx: 2, // x 方向速度
vy: 2, // y 方向速度
radius: 20,
color: 'red'
}
function animate() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 更新位置
ball.x += ball.vx
ball.y += ball.vy
// 边界检测
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
ball.vx = -ball.vx
}
if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
ball.vy = -ball.vy
}
// 绘制球
ctx.beginPath()
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2)
ctx.fillStyle = ball.color
ctx.fill()
// 下一帧
requestAnimationFrame(animate)
}
// 开始动画
animate()四、Canvas vs SVG
1. 详细对比表
| 特性 | Canvas | SVG |
|---|---|---|
| 渲染方式 | 像素(位图) | 矢量(XML) |
| 缩放 | 会失真 | 不失真 |
| 性能 | 大量对象高 | 少量对象高 |
| DOM 支持 | 无 | 完整支持 |
| 事件绑定 | 需手动实现 | 原生支持 |
| 分辨率依赖 | 是 | 否 |
| 文件大小 | 小 | 大(复杂图形) |
| 学习曲线 | 陡峭 | 平缓 |
| 适用场景 | 游戏、图表、图像处理 | 图标、地图、数据可视化 |
2. 选择决策树
需要绘制什么?
│
├─ 高性能动画/游戏?
│ └─ Canvas ✓
│ └─ 例:粒子效果、俄罗斯方块
│
├─ 需要交互和事件?
│ └─ SVG ✓
│ └─ 例:可点击的图表、地图
│
├─ 需要无限缩放?
│ └─ SVG ✓
│ └─ 例:响应式图标、Logo
│
├─ 处理图像/像素?
│ └─ Canvas ✓
│ └─ 例:图片滤镜、截图工具
│
└─ 简单静态图形?
└─ SVG ✓(更简单)
└─ 例:图标、简单图表3. 代码对比
javascript
// Canvas 绘制矩形
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'red'
ctx.fillRect(10, 10, 100, 100)
// 修改矩形?需要重绘整个画布
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = 'blue'
ctx.fillRect(10, 10, 100, 100)
// SVG 绘制矩形
const svg = `
<svg width="200" height="200">
<rect id="myRect" x="10" y="10" width="100" height="100" fill="red" />
</svg>
`
// 修改矩形?直接操作 DOM
const rect = document.getElementById('myRect')
rect.setAttribute('fill', 'blue')
rect.setAttribute('width', '150')
// 添加事件
rect.addEventListener('click', () => {
alert('点击了矩形!')
})五、实际应用场景
1. Canvas 应用
┌──────────────────────────────────────────────────────────┐
│ Canvas 应用场景 │
└──────────────────────────────────────────────────────────┘
✓ 游戏开发
┌──────────────────────────────┐
│ 俄罗斯方块、贪吃蛇等 2D 游戏 │
│ 粒子系统、特效动画 │
│ 高性能要求(60fps) │
└──────────────────────────────┘
✓ 数据可视化
┌──────────────────────────────┐
│ ECharts、Chart.js 等图表库 │
│ 实时数据展示 │
│ 大量数据点渲染 │
└──────────────────────────────┘
✓ 图像处理
┌──────────────────────────────┐
│ 图片滤镜、裁剪、压缩 │
│ 截图工具 │
│ 图片水印 │
└──────────────────────────────┘
✓ 创意效果
┌──────────────────────────────┐
│ 粒子背景、动态效果 │
│ 签名板、画板应用 │
└──────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━2. SVG 应用
┌──────────────────────────────────────────────────────────┐
│ SVG 应用场景 │
└──────────────────────────────────────────────────────────┘
✓ 图标系统
┌──────────────────────────────┐
│ 网站 Logo、功能图标 │
│ 响应式设计(任意缩放) │
│ CSS 动画结合 │
└──────────────────────────────┘
✓ 数据可视化
┌──────────────────────────────┐
│ D3.js 图表 │
│ 交互式图表(点击、悬停) │
│ 地图可视化 │
└──────────────────────────────┘
✓ UI 组件
┌──────────────────────────────┐
│ 进度条、滑块 │
│ 图表仪表盘 │
│ 动态图形界面 │
└──────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━六、面试标准回答
HTML5 提供了强大的多媒体和绘图能力。
音视频方面,通过 audio 和 video 标签,我们可以原生播放音视频,无需 Flash 等第三方插件。支持多种格式、字幕、预加载等功能。JavaScript 可以完全控制播放、暂停、跳转等操作,并能监听各种事件来自定义播放器。
Canvas 是一个 2D 绘图 API,基于像素渲染。它适用于游戏、数据可视化、图像处理等场景。优点是性能好,适合大量对象的动态场景;缺点是不支持缩放,事件绑定复杂。
SVG 是基于 XML 的矢量图形,每个图形都是 DOM 元素。优点是可以无限缩放而不失真,支持事件绑定和 CSS 样式;缺点是复杂图形性能不如 Canvas。
选择上:如果需要高性能动画或处理像素,用 Canvas;如果需要交互、缩放或简单图形,用 SVG。实际项目中,像 ECharts 这样的库会根据场景混合使用两者。
七、记忆口诀
多媒体绘图歌诀:
audio video 播媒体,
原生支持不用急。
Canvas 绘图像素级,
游戏图表都适宜。
SVG 是矢量,
缩放不失真。
图标地图用它好,
交互简单又方便。
性能对比要记牢:
对象多用 Canvas,
交互频繁用 SVG,
根据场景来选择!八、推荐资源
- MDN Canvas 教程
- MDN audio/video
- ECharts 源码 - 学习 Canvas/SVG 混用
- D3.js - SVG 数据可视化库
九、总结一句话
- audio/video: 原生播放 + 丰富 API = 告别 Flash 时代 🎬
- Canvas: 像素渲染 + 高性能 = 游戏图表利器 🎨
- SVG: 矢量图形 + DOM 支持 = 图标地图首选 📊